package com.szyly.epusher.wechat;

import com.szyly.epusher.bean.PhoneUserRet;
import com.szyly.epusher.bean.PushResult;
import com.szyly.epusher.bean.WechatProperties;
import com.szyly.epusher.wechat.bean.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import retrofit2.Response;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


public class WechatApi {
    private Logger logger = LoggerFactory.getLogger(WechatApi.class);

    private final WechatNetApi wechatNetApi;
    private DepartmentApi departmentApi;
    private final WechatProperties properties;
    private TokenResult token;

    private final ConcurrentHashMap<String, String> phoneMap = new ConcurrentHashMap<>();

    public WechatApi(WechatProperties properties) {
        this.properties = properties;
        wechatNetApi = WechatNetApi.Factory.create();
        if (properties.getApi() != null && !properties.getApi().isEmpty()) {
            departmentApi = DepartmentApi.Factory.create(properties.getApi());
        }
    }

    public LicenseResult getLicense() {

        PushResult pushResult = checkWechatProperties();
        if (pushResult.getErrCode() != 0) {
            return new LicenseResult((int) pushResult.getErrCode(), pushResult.getErrMsg());
        }
        if (properties.getApi() == null || properties.getApi().isEmpty()) {
            return new LicenseResult(-1, "epusher.wechat.api必须填写");
        }
        try {
            retrofit2.Response<LicenseResult> execute = departmentApi.getLicenses(properties.getCorpId()).execute();
            if (execute.code() != 200) {
                return new LicenseResult(1000003, "获取许可证失败： " + execute.message());
            }


            LicenseResult licenseResult = execute.body();

            if (licenseResult.getErrCode() == 0) {
                for (License li : licenseResult.getLicenses()) {
                    if (li.getUserid() != null && !li.getUserid().isEmpty()) {
                        UserInfoRet userInfo = getUserInfoByUserId(li.getUserid());
                        if (userInfo.getErrcode() == 0) {
                            li.setUsername(userInfo.getName());
                        } else {
                            li.setUsername("用户不存在");
                        }
                    }

                }
            }

            return licenseResult;
        } catch (IOException e) {
            e.printStackTrace();
            return new LicenseResult(1000004, "获取许可证失败： " + e.getMessage());
        }
    }

    public BatchActiveAccountRet batchActiveAccount(BatchActiveAccountReq batchActiveAccountReq) {
        PushResult pushResult = checkWechatProperties();
        if (pushResult.getErrCode() != 0) {
            return new BatchActiveAccountRet((int) pushResult.getErrCode(), pushResult.getErrMsg());
        }
        if (properties.getApi() == null || properties.getApi().isEmpty()) {
            return new BatchActiveAccountRet(-1, "epusher.wechat.api必须填写");
        }

        BatchActiveAccountReq req = new BatchActiveAccountReq();
        req.setCorpid(properties.getCorpId());

        try {
            retrofit2.Response<BatchActiveAccountRet> execute = departmentApi.batchActiveAccount(batchActiveAccountReq).execute();
            if (execute.code() != 200) {
                return new BatchActiveAccountRet(1000003, "激活失败： " + execute.message());
            }
            return execute.body();
        } catch (IOException e) {
            e.printStackTrace();
            return new BatchActiveAccountRet(1000004, "激活失败： " + e.getMessage());
        }
    }

    public BatchTransferLicenseRet batchTransferLicense(BatchTransferLicenseReq batchActiveAccountReq) {
        PushResult pushResult = checkWechatProperties();
        if (pushResult.getErrCode() != 0) {
            return new BatchTransferLicenseRet((int) pushResult.getErrCode(), pushResult.getErrMsg());
        }
        if (properties.getApi() == null || properties.getApi().isEmpty()) {
            return new BatchTransferLicenseRet(-1, "epusher.wechat.api必须填写");
        }

        BatchActiveAccountReq req = new BatchActiveAccountReq();
        req.setCorpid(properties.getCorpId());

        try {
            retrofit2.Response<BatchTransferLicenseRet> execute = departmentApi.batchTransferLicense(batchActiveAccountReq).execute();
            if (execute.code() != 200) {
                return new BatchTransferLicenseRet(1000003, "转移激活失败： " + execute.message());
            }
            return execute.body();
        } catch (IOException e) {
            e.printStackTrace();
            return new BatchTransferLicenseRet(1000004, "转移激活失败： " + e.getMessage());
        }
    }

    public PushResult checkWechatProperties() {
        if (!StringUtils.hasText(properties.getCorpId()) || properties.getAgentId() <= 0 || !StringUtils.hasText(properties.getSecret())) {
            return new PushResult(1000001, "参数未配置或者未配置完全");
        }
        return new PushResult(0, "ok");
    }

    public PushResult getToken() {
        PushResult pushResult = checkWechatProperties();
        if (pushResult.getErrCode() != 0) {
            return pushResult;
        }

        try {
            retrofit2.Response<TokenResult> execute = wechatNetApi.getToken(properties.getCorpId(), properties.getSecret()).execute();
            if (execute.code() != 200) {
                return new PushResult(1000003, "获取token失败： " + execute.message());
            }

            TokenResult tokenResult = execute.body();

            if (tokenResult.getErrcode() != 0) {
                return new PushResult(tokenResult.getErrcode(), tokenResult.getErrmsg());
            }

            token = tokenResult;
            token.setExpired_time(new Date(System.currentTimeMillis() + tokenResult.getExpires_in() * 800));
            return new PushResult(0, "ok");
        } catch (IOException e) {
            e.printStackTrace();
            return new PushResult(1000004, "获取token失败： " + e.getMessage());
        }
    }

    public PushResult checkToken() {

        logger.info("token: " + token);
        if (token == null || token.getExpired_time().getTime() < System.currentTimeMillis()) {
            return getToken();
        }
        return new PushResult(0, "ok");
    }

    public PhoneUserRet getUserIdByPhoneNumber(String phoneNumber) {
        if (phoneMap.containsKey(phoneNumber)) {
            return new PhoneUserRet(0, "ok").setUserid(phoneMap.get(phoneNumber));
        }
        PushResult pushResult = checkToken();
        if (pushResult.getErrCode() != 0) {
            return new PhoneUserRet(pushResult.getErrCode(), pushResult.getErrMsg());
        }

        try {
            Response<PhoneUserRet> execute = wechatNetApi.getUserId(token.getAccess_token(), new PhoneUserReq(phoneNumber)).execute();
            if (execute.code() != 200) {
                return new PhoneUserRet(1000003, "获取token失败： " + execute.message());
            }
            PhoneUserRet tokenResult = execute.body();
            if (tokenResult.getErrcode() == 0) {
                phoneMap.put(phoneNumber, tokenResult.getUserid());
            }
            return tokenResult;
        } catch (IOException e) {
            e.printStackTrace();
            return new PhoneUserRet(1000004, "通过手机号获取用户失败： " + e.getMessage());

        }

    }

    public UserInfoRet getUserInfoByUserId(String userId) {

        PushResult pushResult = checkToken();
        if (pushResult.getErrCode() != 0) {
            return new UserInfoRet((int) pushResult.getErrCode(), pushResult.getErrMsg());
        }

        try {
            Response<UserInfoRet> execute = wechatNetApi.getUserInfoByUserId(token.getAccess_token(), userId).execute();
            if (execute.code() != 200) {
                return new UserInfoRet(1000003, "获取token失败： " + execute.message());
            }
            return execute.body();
        } catch (IOException e) {
            e.printStackTrace();
            return new UserInfoRet(1000004, "通过用户ID获取用户信息失败： " + e.getMessage());

        }

    }


    public PushResult sendMessage(WechatMsg message) {
        PushResult pushResult = checkToken();
        if (pushResult.getErrCode() != 0) {
            return pushResult;
        }
        try {
            message.setAgentid(properties.getAgentId());
            Response<MsgResult> execute = wechatNetApi.sendMessage(token.getAccess_token(), message).execute();
            if (execute.code() != 200) {
                return new PushResult(1000003, "发送消息失败： " + execute.message());
            }
            MsgResult tokenResult = execute.body();
            return new PushResult(tokenResult.getErrcode(), tokenResult.getErrmsg());
        } catch (IOException e) {
            e.printStackTrace();
            return new PushResult(1000004, "发送消息失败： " + e.getMessage());

        }

    }

    public PushResult sendPhoneMessage(String type, String phoneNumber, String message) {
        PhoneUserRet phoneUserRet = getUserIdByPhoneNumber(phoneNumber);
        if (phoneUserRet.getErrcode() != 0) {
            return new PushResult(phoneUserRet.getErrcode(), phoneUserRet.getErrmsg());
        }
        if (MessageType.TEXT.equals(type)) {
            return sendMessage(getTextMessage(phoneUserRet.getUserid(), message));
        } else if (MessageType.MARKDOWN.equals(type)) {
            return sendMessage(getMarkdownMessage(phoneUserRet.getUserid(), message));
        }
        return new PushResult(1000005, "发送消息失败： 消息类型错误");
    }

    public PushResult sendPhoneMessages(String type, List<String> phoneNumbers, String message) {
        StringBuilder stringBuilder = new StringBuilder();
        for (String phoneNumber : phoneNumbers) {
            PushResult pushResult = sendPhoneMessage(type, phoneNumber, message);
            if (pushResult.getErrCode() != 0) {
                stringBuilder.append(pushResult.getErrMsg() + ",");
            }
        }
        return new PushResult(0, stringBuilder.toString());
    }

    public WechatMsg getMarkdownMessage(String touser, String content) {
        return new WechatMsg()
                .setMsgtype("markdown")
                .setTouser(touser)
                .setMarkdown(new WechatMsg.TextBean()
                        .setContent(content))
                .setSafe(0);
    }

    public WechatMsg getTextMessage(String touser, String content) {
        return new WechatMsg()
                .setMsgtype("text")
                .setTouser(touser)
                .setText(new WechatMsg.TextBean()
                        .setContent(content))
                .setSafe(0);
    }


    public LicenseResult activeAccounts(List<ActiveRequest> activeRequests) {
        BatchActiveAccountReq activeAccountReq = new BatchActiveAccountReq(properties.getCorpId(), new ArrayList<>());
        BatchTransferLicenseReq transferLicenseReq = new BatchTransferLicenseReq(properties.getCorpId(), new ArrayList<>());
        for (ActiveRequest activeRequest : activeRequests) {
            if (activeRequest.getOldUserId() == null) {
                activeAccountReq.getActive_list().add(new BatchActiveAccountReq.ActiveListDTO(activeRequest.getActiveCode(), activeRequest.getActiveUserId()));
            } else {
                transferLicenseReq.getTransfer_list().add(new BatchTransferLicenseReq.TransferListDTO(activeRequest.getOldUserId(), activeRequest.getActiveUserId()));
            }

        }
        int err = 0;
        if (activeAccountReq.getActive_list().size() > 0) {
            BatchActiveAccountRet batchActiveAccountRet = batchActiveAccount(activeAccountReq);
            if (batchActiveAccountRet.getErrcode() != 0) {
                return new LicenseResult(batchActiveAccountRet.getErrcode(), batchActiveAccountRet.getErrmsg());

            }

            for (BatchActiveAccountRet.ActiveResultDTO activeResultDTO : batchActiveAccountRet.getActive_result()) {
                if (activeResultDTO.getErrcode() != 0) {
                    err++;
                }

            }

        }
        if (transferLicenseReq.getTransfer_list().size() > 0) {
            BatchTransferLicenseRet batchTransferLicenseRet = batchTransferLicense(transferLicenseReq);
            if (batchTransferLicenseRet.getErrcode() != 0) {
                return new LicenseResult(batchTransferLicenseRet.getErrcode(), batchTransferLicenseRet.getErrmsg());

            }
            for (BatchTransferLicenseRet.TransferResultDTO transferResultDTO : batchTransferLicenseRet.getTransfer_result()) {
                if (transferResultDTO.getErrcode() != 0) {
                    err++;
                }
            }
        }
        return new LicenseResult(err, err > 0 ? "部分用户激活失败，请刷新" : null);
    }
}
